<?php


namespace App\Utility;


use EasySwoole\Component\Singleton;
use EasySwoole\EasySwoole\Config;
use EasySwoole\Jwt\Exception;
use EasySwoole\Jwt\Jwt;

/**
 * JWT
 * Class JwtManager
 * @package App\Utility
 */
class JwtManager
{
    use Singleton;

    /**
     * 生成token
     * @param int $uid
     * @param $userId
     * @param string $username
     * @param array $data
     * @return string
     */
    function encode(int $uid, $userId, string $username, array $data = []): string
    {
        // jwt配置
        $jwtConfig = Config::getInstance()->getConf("jwt");

        // 当前时间
        $time = time();

        // 加密方式
        $algorithm = $jwtConfig['algorithm'] ?? 'HMACSHA256';

        // 密钥
        $key = $jwtConfig['key'] ?? 'easyswoole';

        // 过期时间
        $exp = $jwtConfig['exp'] ?? 3600;

        // 发行人
        $iss = $jwtConfig['iss'] ?? 'easyswoole';

        // 在此之前不可用
        $nbf = $jwtConfig['nbf'] ?? 10;

        // 在此之前不可用
        $sub = $jwtConfig['sub'] ?? 'easyswoole';

        $jwtObject = Jwt::getInstance()
            ->setSecretKey($key) // 秘钥;
            ->publish();

        $jwtObject->setAlg($algorithm); // 加密方式
        $jwtObject->setAud($username); // 用户
        $jwtObject->setExp($time + $exp); // 过期时间
        $jwtObject->setIat($time); // 发布时间
        $jwtObject->setIss($iss); // 发行人
        $jwtObject->setJti(md5($time)); // jwt id 用于标识该jwt
        $jwtObject->setNbf($time - $nbf); // 在此之前不可用
        $jwtObject->setSub($sub); // 主题

        // 自定义数据
        $jwtObject->setData([
            'uid' => $uid,
            'userId' => $userId,
            'username' => $username,
            'data' => $data
        ]);

        // 最终生成的token
        return $jwtObject->__toString();
    }

    /**
     * 解析token
     * @param string|null $token
     * @return array
     */
    function decode(?string $token)
    {
        $JWTConfig = Config::getInstance()->getConf("jwt");

        // 密钥
        $key = $JWTConfig['key'] ?? 'easyswoole';

        // 主题
        $sub = $JWTConfig['sub'] ?? 'easyswoole';

        $result = [
            'code' => 400,
            'result' => null
        ];

        try {
            $jwtObject = Jwt::getInstance()
                ->setSecretKey($key)
                ->decode($token);

            $status = $jwtObject->getStatus();

            switch ($status) {
                case -2:
                    $result['msg'] = 'TOKEN过期';
                    break;
                case -1:
                    $result['msg'] = 'TOKEN无效';
                    break;
                case  1:
                    $jwtSub = $jwtObject->getSub();
                    $aud = $jwtObject->getAud();
                    $data = $jwtObject->getData();

                    switch (1) {
                        case $jwtSub !== $sub:
                            $result['msg'] = "所面向的用户异常";
                            break;
                        case $data['username'] !== $aud:
                            $result['msg'] = "非法用户";
                            break;
                        default:
                            $result = [
                                'code' => 200,
                                'result' => $jwtObject->getData(),
                                'msg' => 'success'
                            ];
                            break;
                    }
                    break;
                default:
                    $result['msg'] = 'TOKEN解析异常';
            }
        } catch (\EasySwoole\Jwt\Exception $e) {
            $result['msg'] = 'TOKEN解析异常';
        }

        return $result;
    }

    /**
     * 生成token
     * @param int $uid
     * @param int $userId
     * @param string $username
     * @param int $type
     * @param array $data
     * @return string
     */
    function encodeStaff(int $uid, int $userId, string $username, int $type, array $data = []): string
    {
        // jwt配置
        $jwtConfig = Config::getInstance()->getConf("jwt");

        // 当前时间
        $time = time();

        // 加密方式
        $algorithm = $jwtConfig['algorithm'] ?? 'HMACSHA256';

        // 密钥
        $key = $jwtConfig['key'] ?? 'easyswoole';

        // 过期时间
        $exp = $jwtConfig['exp'] ?? 3600;

        // 发行人
        $iss = $jwtConfig['iss'] ?? 'easyswoole';

        // 在此之前不可用
        $nbf = $jwtConfig['nbf'] ?? 10;

        // 在此之前不可用
        $sub = $jwtConfig['sub'] ?? 'easyswoole';

        $jwtObject = Jwt::getInstance()
            ->setSecretKey($key) // 秘钥;
            ->publish();

        $jwtObject->setAlg($algorithm); // 加密方式
        $jwtObject->setAud($username); // 用户
        $jwtObject->setExp($time + $exp); // 过期时间
        $jwtObject->setIat($time); // 发布时间
        $jwtObject->setIss($iss); // 发行人
        $jwtObject->setJti(md5($time)); // jwt id 用于标识该jwt
        $jwtObject->setNbf($time - $nbf); // 在此之前不可用
        $jwtObject->setSub($sub); // 主题

        // 自定义数据
        $jwtObject->setData([
            'uid' => $uid,
            'userId' => $userId,
            'username' => $username,
            'type' => $type,
            'data' => $data
        ]);

        // 最终生成的token
        return $jwtObject->__toString();
    }

}